home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 19 / CU Amiga Magazine's Super CD-ROM 19 (1998)(EMAP Images)(GB)[!][issue 1998-02].iso / CUCD / Programming / LEDA / source / src / graph_alg / _transclosure.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-16  |  3.7 KB  |  182 lines

  1. /*******************************************************************************
  2. +
  3. +  LEDA  3.1c
  4. +
  5. +
  6. +  _transclosure.c
  7. +
  8. +
  9. +  Copyright (c) 1994  by  Max-Planck-Institut fuer Informatik
  10. +  Im Stadtwald, 6600 Saarbruecken, FRG     
  11. +  All rights reserved.
  12. *******************************************************************************/
  13.  
  14.  
  15.  
  16. /*******************************************************************************
  17. *                                                                              *
  18. *  TRANSITIVE_CLOSURE (transitive closure)                                     *
  19. *                                                                              *
  20. *******************************************************************************/
  21.  
  22. #include <LEDA/graph_alg.h>
  23.  
  24. typedef list<node>* nodelist_ptr;
  25.  
  26.  
  27.  
  28.  
  29. static void acyclic_transitive_closure(graph& G)
  30. { // computes transitive closure of acyclic graph G
  31.  
  32. node v,w;
  33.  
  34. int i,j,k,h;
  35. int n = G.number_of_nodes();
  36.  
  37. TOPSORT1(G); 
  38.  
  39. node_array<int> marked(G);
  40. node_array<int> top_ord(G);   // topologic order
  41. node_array<int> chain(G);     // chain[v] = i  iff  v in C[i]
  42.  
  43. node_list* C = new node_list[n+1];  // chains C[0], C[1], ...
  44.  
  45. node*      N = new node[n];         // N[i] = i-th node in topological order
  46.  
  47. int**      reach = new int*[n];     // reach[h][i] = min { j ; N[j] in C[h] and
  48.                                     // there is a path from N[i] to N[j] }
  49.  
  50.  
  51. for(i=0; i<n; i++) reach[i] = new int[n];
  52.  
  53. i=0;
  54. forall_nodes(v,G) { marked[v]=1; top_ord[v] = i; N[i]=v; i++; }
  55.  
  56. // compute chain decomposition C[0], C[1], ..., C[k]
  57.  
  58. k=0;
  59. forall_nodes(v,G) 
  60.  { node v0 = v;
  61.    if (marked[v0])
  62.     {  C[k].append(v0);  
  63.        chain[v0]=k;
  64.        while (v0 != nil)
  65.        { node u = nil;
  66.          forall_adj_nodes(w,v0) 
  67.            if (marked[w]) 
  68.            {  u = w;
  69.               break; 
  70.             }
  71.  
  72.          if (u != nil) 
  73.          { marked[u]=0;
  74.            chain[u]=k;
  75.            C[k].append(u);
  76.           }
  77.          v0=u;
  78.         }
  79.        k++;
  80.     }
  81.   }
  82. k--;
  83.  
  84.  
  85. for(h=0; h<n; h++)
  86.   for(i=0; i<n; i++)
  87.     reach[h][i] = n+1;
  88.  
  89. Forall_nodes(v,G)       //decreasing order
  90. { i=top_ord[v];
  91.   forall_adj_nodes(w,v) //increasing order
  92.   { j=top_ord[w];
  93.     if (j <= reach[chain[w]][j])
  94.      for(h=0; h<=k; h++)
  95.        if (reach[h][j] < reach[h][i]) reach[h][i] = reach[h][j];
  96.   }
  97.   reach[chain[v]][i] = i;
  98. }
  99.  
  100.  
  101. G.del_all_edges();
  102.  
  103. forall_nodes(v,G)
  104.   for(i=0; i<=k; i++)
  105.     { j = reach[i][top_ord[v]];
  106.       if ( j < n+1 )
  107.         for(w = N[j]; w != nil; w = C[i].succ(w)) G.new_edge(v,w);
  108.      }
  109.  
  110.  
  111. for(i=0; i<=k; i++) C[i].clear();
  112. delete[] C;
  113.  
  114. for(i=0; i<n; i++) delete reach[i];
  115. delete reach;
  116.  
  117. delete N;
  118.  
  119. }
  120.  
  121.  
  122. graph TRANSITIVE_CLOSURE(const graph& G0)
  123. {
  124.   node v,w;
  125.   edge e;
  126.   int i,j;
  127.  
  128.   graph G = G0;
  129.  
  130.   node_array<int> compnum(G);
  131.   int k = STRONG_COMPONENTS(G,compnum);
  132.  
  133. /* reduce graph G to graph G1 = (V',E') 
  134.    with V' = { V[0],V[1],...,V[k] } = set of scc's of G
  135.    and (V[i],V[j]) in E' iff there is an edge from V[i] to V[j] in G
  136.  
  137.    G1.inf(V[i]) = set of nodes v in G with v in scc i (i.e. compum[v] = i)
  138. */
  139.  
  140.   GRAPH<nodelist_ptr,int> G1;
  141.  
  142.   node*  V = new node[k];
  143.  
  144.   for(j=0; j < k; j++) V[j] = G1.new_node(new list<node>);
  145.  
  146.   forall_nodes(v,G) 
  147.   { int i = compnum[v];
  148.     G1[V[i]]->append(v);
  149.    }
  150.   
  151.   forall_edges(e,G)
  152.   { i = compnum[source(e)];
  153.     j = compnum[target(e)];
  154.     if (i!=j) G1.new_edge(V[i],V[j]);
  155.    }
  156.  
  157.   eliminate_parallel_edges(G1);
  158.   
  159.   // compute transitive closure of acyclic graph G1
  160.  
  161.   acyclic_transitive_closure(G1);
  162.  
  163.   G.del_all_edges();
  164.   
  165.   list_item x,y;
  166.  
  167.   forall_nodes(v,G1)
  168.   { list<node>* plv = G1[v];
  169.     forall_adj_nodes(w,v)
  170.        forall_items(x,*plv)
  171.           forall_items(y,*(G1[w])) G.new_edge(plv->inf(x),G1[w]->inf(y));
  172.    }
  173.   
  174.    forall_nodes(v,G1) delete G1[v];
  175.   
  176.    delete V;
  177.  
  178.    return G;
  179. }
  180.  
  181.